今天應該就進入到所有權的尾聲,會為前幾天的文章內容做一些補充
接下來要補充的是,當我們要同時 move 給多個變數,該怎麼做
沿用前兩天的例子
fn main() {
let drink1 = String::from("Milk Tea");
let drink2 = drink1;
let drink3 = drink1;
}
我們來執行一下,出現了錯誤訊息
來回想一下所有權的規則
每個值一次只能有一個 owner ,
我們在 move 的時候會將所有權給 drink2,但如果接下來要給其他變數,這樣是不可能的
以生活例子來說, drink1 現在有一杯奶茶,他要將這杯奶茶給 drink2
給了 drink2 後, drink1 手上就沒東西了,他沒辦法再給 drink3
> cargo run
error[E0382]: use of moved value: `drink1`
--> src/main.rs:5:18
|
2 | let drink1 = String::from("Milk Tea");
| ------ move occurs because `drink1` has type `String`, which does not implement the `Copy` trait
3 |
4 | let drink2: String = drink1;
| ------ value moved here
5 | let drink3 = drink1;
| ^^^^^^ value used here after move
|
help: consider cloning the value if the performance cost is acceptable
|
4 | let drink2: String = drink1.clone();
| ++++++++
For more information about this error, try `rustc --explain E0382`.
warning: `hello_world` (bin "hello_world") generated 2 warnings
error: could not compile `hello_world` (bin "hello_world") due to previous error; 2 warnings emitted
那解法是什麼?我們可以用 Clone 這個 trait
Clone 這個 trait 會幫我們複製 drink1 一模一樣的值出來,
而他們指向的記憶體位址是不一樣的,
可以把它想像成是做出一個複製奶茶出來,
而原本的奶茶所有權還是在 drink1 手上
複製出來的奶茶所有權在 drink2 手上
drink2 就可以將這杯複製奶茶給 drink3
fn main() {
let drink1 = String::from("Milk Tea");
let drink2: String = drink1.clone();
let drink3 = drink2;
println!("drink1 is {}", drink1);
println!("drink3 is {}", drink3);
}
> cargo run
drink1 is Milk Tea
drink3 is Milk Tea
那 drink2 呢? drink2 將值的所有權給了 drink3
所以之後 drink2 就不會再有複製奶茶的所有權了
fn main() {
let drink1 = String::from("Milk Tea");
let drink2: String = drink1.clone();
let drink3 = drink2;
println!("drink1 is {}", drink1);
println!("drink2 is {}", drink2);
println!("drink3 is {}", drink3);
}
> cargo run
8 | println!("drink2 is {}", drink2);
| ^^^^^^ value borrowed here after move
不過基本型別就不是使用 move 以及 clone trait
我們來介紹一下基本型別
基本型別像是 integer
、 Float
、 Boolean
,
他們的 value 是固定的,就只會存在於 Stack 中
如果我們今天要將一個基本型別變數的值,給另一個變數指向,
實際上是使用了 copy 這個 trait 將值進行複製,
這邊就不會有所有權的轉移問題,
因為 number1 的值並沒有轉移給 number2,
而是用 copy 的方式,讓 number2 的值跟 number1 一樣
fn main() {
let number1 = 1;
let number2 = number1;
println!("number1 is {}", number1);
println!("number2 is {}", number2)
}
我們來看一下執行結果
> cargo run
number1 is 1
number2 is 1